home *** CD-ROM | disk | FTP | other *** search
- #include <string.h>
- #include <stdio.h>
- #include <stdarg.h>
-
- #include "DeskLib:WimpSWIs.h"
- #include "DeskLib:Error.h"
-
- #include "Shell.Shell.h"
- #include "Shell.Extra.h"
- #include "Shell.SafeAlloc.h"
- #include "Shell.TextRect.h"
-
-
-
- #define Shell_TEXT_INCREMENT 4096
- /* Text is stored in a malloc-ed block which is a multiple of this size */
- /* so as to avoid repeadly realloc-ing */
-
-
-
- typedef struct { /* this is used to record a reference point in some */
- int line; /* text. 'offset' is the position in text of the first */
- int offset; /* chr of line-number 'line'. */
- }
- Shell_textref;
-
-
- typedef struct {
- char *text; /* The text. */
- int datasize, /* Length of text *excluding* the '\0'. */
- maxdatasize; /* Space currently rserved for text (excl '\0').*/
- int numlines, /* The number of lines in the text... */
- maxlinelen; /* Used to check whether window is wide enough. */
- Shell_textref top, bottom, last; /* 'top' is for top visible line in the window. */
- } /* 'bottom' is for the last visible line. */
- Shell_textrectblock; /* 'last' is for the last line in the text. */
- /* 'top' and 'bottom' are updated each time any */
- /* part of the text is re-drawn, and are set to */
- /* first and last line of the redrawn text. */
-
-
-
-
-
- static int Shell_TextRectFindLineNumber( const Shell_textrectblock *info, int line)
- /* This function returns the position of the first charater of line number 'line' */
- /* in info->text. It finds which reference point is nearest to line number 'line, */
- /* then counts forward or backwards, counting line-feeds until is reaches the start of */
- /* line-number 'line'. */
- /* It all looks a bit long-winded, partly 'cos I've tried to make it run fast. */
- /* It should really be in assembler for speed, but I don't know nearly enough for that. */
- {
- Shell_textref nearest;
- int step;
-
- if ( line >= info->numlines) return -1;
- if ( line == 0) return 0;
-
- /* find reference line that is closest to line */
-
- if ( line <= info->top.line) {
- if ( (line-info->top.line-line) < line-0 ) {
- nearest = info->top;
- step = -1;
- }
- else {
- nearest.line=0;
- nearest.offset =0;
- step = +1;
- }
- }
-
- else if ( line <= info->bottom.line) {
- if ((info->bottom.line-line) < (line-info->top.line)) {
- nearest = info->bottom;
- step = -1;
- }
- else {
- nearest = info->top;
- step = +1;
- }
- }
-
- else {
- if ((info->last.line-line) < (line-info->bottom.line)) {
- nearest = info->last;
- step = -1;
- }
- else {
- nearest = info->bottom;
- step = +1;
- }
- }
-
-
- /* now step along from the reference line, counting LF's until we have reached the line... */
-
- if ( step > 0) {
- for ( ; nearest.line != line; nearest.offset++) {
- if ( info->text[nearest.offset]=='\n') nearest.line++;
- }
- }
- else {
- for ( nearest.offset -= 2; nearest.line != line; nearest.offset--) {
- if ( info->text[nearest.offset]=='\n') nearest.line--;
- }
- nearest.offset+=2;
- }
-
-
- /* nearest.offset is position in info->text of the first chr of line-number 'line'.*/
- /* Just check here that this position is not outside the range of the text, to */
- /* prevent subsequent overwriting of memory. */
-
- if ( nearest.offset < 0 || nearest.offset > info->datasize)
- Error_ReportFatal( 1, Error_PLACE "Error in Shell_TextRectFindLineNumber");
-
- return nearest.offset;
- }
-
-
-
-
-
-
- static BOOL Shell_TextRectSaver( char *filename, Shell_rectblock *r)
- {
- FILE *f;
- Shell_textrectblock *textrectblock = (Shell_textrectblock *) r->reference;
-
- f = fopen( filename, "w");
- if ( !f) return FALSE;
-
- fprintf( f, textrectblock->text);
- fclose(f);
-
- return TRUE;
- }
-
-
-
-
-
- #define Min( a, b) ( (a) < (b) ) ? (a) : (b)
-
- static int Shell_TextRectRAMSaver(
- task_handle sourcetask,
- Shell_rectblock *r,
- task_handle desttask,
- void *destbuffer,
- unsigned int buffersize,
- int progress
- )
- {
- Shell_textrectblock *textrectblock = (Shell_textrectblock *) r->reference;
- int n;
-
- n = Min( textrectblock->datasize - progress, buffersize);
- /* The length of the text in the rect is ...->datasize. This excludes */
- /* the '\0', which looks a bit funny if included into a text editor */
-
- Wimp_TransferBlock(
- sourcetask, textrectblock->text + progress,
- desttask, destbuffer,
- n
- );
- return n;
- }
-
-
-
-
-
-
-
-
-
-
-
-
- static void Shell_TextRectRedrawer(
- Shell_convertpoint convert,
- wimp_point rectsize,
- void *reference,
- const wimp_rect *redrawrect
- )
-
- { Shell_textrectblock *info = reference;
- wimp_rect rect = *redrawrect;
- int n;
- char *c;
-
- Shell_ConvertToSubTextRect2( &rect, rectsize);
-
- n = Shell_TextRectFindLineNumber( info, rect.min.y);
-
- if ( n!= -1) {
- c = &info->text[n];
- info->top.line = rect.min.y; /* Update top reference point. */
- info->top.offset = n; /* This will be useful in subsequent redraws */
- if ( rect.max.y > info->numlines) rect.max.y = info->numlines;
- { int y;
- char *cc;
- for ( y=rect.min.y, cc=c; y<=rect.max.y; y++, c=cc+1) {
- /* print line number y. Put a '\0' temporarily at end of line */
- cc = strchr( c, '\n'); if (cc) *cc=0;
- Shell_PrintString(
- c, 0, rectsize.y - y*Shell_TEXTYSIZE, convert
- );
- if (cc) *cc = '\n';
- else break;
- }
- info->bottom.line = y;
- info->bottom.offset = ( c - info->text);
- }
- }
- return;
- }
-
-
-
-
-
-
-
- Shell_rectblock *Shell_AddTextRect( Shell_windblock *w, int x, int y, int forecol, int backcol)
- {
- Shell_textrectblock *info = Shell_SafeMalloc( sizeof( Shell_textrectblock));
- Shell_rectblock *r;
-
- info->text = Shell_SafeMalloc( 1+Shell_TEXT_INCREMENT); info->text[0] = 0;
- info->maxdatasize = Shell_TEXT_INCREMENT;
- info->datasize = 0;
- info->maxlinelen = 0;
- info->numlines = 1;
- info->last.line = 0;
- info->top.line = 0;
- info->bottom.line = 0;
- info->last.offset = 0;
- info->top.offset = 0;
- info->bottom.offset = 0;
-
- r = Shell_AddRectangle2(
- w, x, y-Shell_TEXTYSIZE, x+Shell_TEXTXSIZE, y,
- Shell_TextRectRedrawer, info
- );
-
- Shell_MakeRectIcon( r, forecol, backcol, "R2");
-
- r->saver = Shell_TextRectSaver;
- r->ramsaver = Shell_TextRectRAMSaver;
- r->size = 0;
-
- return r;
- }
-
-
-
-
-
-
-
- Shell_rectblock *Shell_defaulttextrectblock = NULL; /* Not opened yet. */
-
-
-
-
-
-
- void Shell_TextRectPrint( Shell_rectblock *rect, const char *text)
- { int extraneeded;
- int lastLF, numlines, size;
- Shell_textrectblock *info;
-
-
- /* Check whether the rect is Shell_'s default textrect */
- /* and open a window + textrect if one isn't opened already */
-
- if ( rect == Shell_defaulttextrect) rect = Shell_defaulttextrectblock;
- /* Plot to the default text-rect window. */
-
- if ( rect == NULL) {
- rect = Shell_defaulttextrectblock =
- Shell_AddTextRect(
- Shell_OpenGFXWindow(),
- 0,
- 0,
- colour_BLACK,
- colour_TRANSPARENT
- );
- }
- /* Have to open a new window, and add a textrect */
-
-
- if ( text[0]==0) return;
-
- /* Can now do the actual text-printing... */
- /* This involves adding 'text' to the end of the existing text. */
- /* We have to calculate how many lines are added, whether the */
- /* max-linelength has increased, etc. */
-
- info = (Shell_textrectblock *) rect->reference;
-
- /* Count number of linefeeds in the new text, also find length, and */
- /* max line-length. Could do this with str* functions, but this will be */
- /* quicker as it only loops through the text once. */
-
- {
- char *c = (char *) text;
- int linelen;
-
- size = 0;
- numlines = 0;
-
- lastLF = -(int) ( info->datasize - info->last.offset) - 1;
- /* last.offset is ptr to chr *after* the last '\n', so this makes lastLF */
- /* be the position of the last '\n' */
-
- for ( ; ; c++, size++) {
- if ( *c == '\n' || ( !*c) ) {
- linelen = (int) ( c-text) - lastLF - 1;
- if ( linelen > info->maxlinelen) info->maxlinelen = linelen;
- if ( *c) {
- lastLF = c-text;
- numlines++;
- }
- }
- if (!*c) break;
- }
- }
-
-
- extraneeded = info->datasize + size - info->maxdatasize;
-
- if ( extraneeded > Shell_TEXT_INCREMENT) {
- info->text = Shell_SafeRealloc( info->text, info->datasize+size+1);
- info->maxdatasize = info->datasize + size;
- }
- else if ( extraneeded > 0) {
- info->text = Shell_SafeRealloc( info->text, info->maxdatasize+Shell_TEXT_INCREMENT+1);
- info->maxdatasize += Shell_TEXT_INCREMENT;
- }
-
- strcpy( &info->text[ info->datasize], text);
-
- if ( lastLF>=0) {
- info->last.offset = lastLF + info->datasize+1; /* datasize is still old value */
- /* ptr is to the chr AFTER the LF */
- info->last.line += numlines;
- info->numlines += numlines;
- }
-
- info->datasize += size;
- rect->size = info->datasize;
-
- {
- int oldrectminy = rect->rect.min.y;
- BOOL yscrollbottom = Shell_CheckYScrollIsBottom( rect->window);
- wimp_rect newrect; /* This is the new rect at the bottom. */
-
- rect->rect.max.x = rect->rect.min.x + Shell_TEXTXSIZE * info->maxlinelen;
- rect->rect.min.y = rect->rect.max.y - Shell_TEXTYSIZE * info->numlines;
-
- Shell_ResizeIconRect( rect);
-
- newrect = rect->rect;
- newrect.max.y = oldrectminy + Shell_TEXTYSIZE;
-
- /*Shell_CheckWindSizeAndRedraw( rect->window, &rect->icon.workarearect);*/
- Shell_CheckWindSizeAndRedraw( rect->window, &newrect);
-
- if ( yscrollbottom) Shell_MoveYScrollToBottom( rect->window);
- }
- }
-
-
-
-
-
- void Shell_TextRectPrintf( Shell_rectblock *rectblock, const char *fmt, ...)
- { va_list args;
- int len;
-
- len = strlen( fmt);
- if ( len > Shell_stringMAX) {
- Error_Report( 0,
- "Format string length %i is too long for Shell_TextRectPrintf. Max length is %i",
- len, Shell_stringMAX
- );
- Shell_TextRectPrint( rectblock, "*** string too long for Shell_TextRectPrintf ***\n");
- return;
- }
-
- va_start( args, fmt);
- vsprintf( Shell_string, fmt, args);
- va_end( args);
-
- len = strlen( Shell_string);
- if ( len > Shell_stringMAX) {
- Error_Report( 0,
- "Expanded string length %i is too long (max is %i). Shell must exit.",
- len, Shell_stringMAX
- );
- exit( 1);
- }
-
- Shell_TextRectPrint( rectblock, Shell_string);
- }
-
-
-
-